<?php
/*
 * Camelot PHP Tools
 *
 * @version 2.0
 * @author Bendsoft
 * @package PHP Tools
 * @subpackage Camelot
 * @license FreeBSD License (www.bendsoft.com/licensing/)
 * 
 */

if (!isset($_SESSION)) {
    session_start();
}

/**
 * Camelot Soap Connection Client
 * 
 * @author Bendsoft
 */
class CamelotSoapClient extends CamelotExceptionHandling {

    public $client;

    /**
     * Construct the CamelotSoapClient object
     * 
     * @param WcfSettingsObject $settings
     * @param string $auth 
     */
    public function __construct(WcfSettingsObject $settings) {

        // Array with SOAP Options, check http://www.php.net/manual/en/soapclient.soapclient.php for full listing of options
        // Note! The wsdloptions is only used if the $authentication_method is set to default
        $wsdloptions = array(
            'soap_version' => $settings->wsdl_soap_version,
            'exceptions' => $settings->wsdl_exceptions,
            'trace' => $settings->wsdl_trace
        );

        // Ensure $authentication_method is lowercase
        $authentication_method = strtolower($settings->authentication_method);

        // Select authentication method
        switch ($authentication_method) {
            // If security is set to <security mode="None"/> in the Camelot SharePoint Integration Service Config
            default:
            case "default":
                try {
                    $this->client = new SoapClient($settings->wsdl_address, $wsdloptions);
                    $this->commandStatus = true;
                } catch (SoapFault $exc) {
                    $this->commandStatus = false;
                    $this->exception = new CamelotException($exc);
                }
                break;

            // If security is set to <transport clientCredentialType="Ntlm"/> in the Camelot SharePoint Integration Service Config
            case "ntlm":

                // If there are incoming credentials from a form
                if ($_POST) {
                    if (isset($_POST['ntlm_username']) && isset($_POST['ntlm_password'])) {
                        $_SESSION['NTLM_CREDENTIALS'] = $_POST;
                    }
                }

                // Verify the NTLM_CREDENTIALS is set, if not lets display a login form and kill the application
                if (!isset($_SESSION['NTLM_CREDENTIALS'])) {
                    $this->displayLogin();
                    die;
                }

                try {

                    // Fire up the client
                    $this->client = new CamelotNTLMSoapClient($settings->wsdl_address, $_SESSION['NTLM_CREDENTIALS']);
                    $this->commandStatus = true;

                    // Check if the client is an object, if not lets display the login form once again and unset the session
                    if (!is_object($this->client->GetServerTime())) {
                        echo "You could not be logged on to the Domain,<br />please try again!<br />";
                        session_unset($_SESSION['NTLM_CREDENTIALS']);
                        $this->displayLogin();
                        die;
                    }
                } catch (SoapFault $exc) {
                    $this->commandStatus = false;
                    $this->exception = new CamelotException($exc);
                    session_unset($_SESSION['NTLM_CREDENTIALS']);
                }


                break;
        }
    }

    /**
     * Display the default ntlm login form
     */
    private function displayLogin() {
        ?>
        <h3>Login to domain</h3>
        <form action="?" method="post">
            <label for="ntlm_username">Ntlm Username:</label>
            <input type="text" name="ntlm_username" id="ntlm_username" /><br />
            <label for="ntlm_password">Ntlm Password:</label>
            <input type="password" name="ntlm_password" id="ntlm_password" /><br />
            <input type="submit" />
        </form>
        <?php
    }

}

/**
 * Camelot Soap Connection Client for NTLM Authentication
 * 
 * @author Bendsoft
 */
class CamelotNTLMSoapClient extends NTLMSoapClient {

    /**
     * The ntlm username as ntlm_username
     * @var string
     */
    protected $user;

    /**
     * The ntlm password as ntlm_password
     * @var string
     */
    protected $password;

    /**
     * Construct the CamelotNTLMSoapClient object
     * 
     * @param string $wsdl The WSDL address
     * @param array $options 
     */
    public function __construct($wsdl, $options = array()) {
        $this->user = $options['ntlm_username'];
        $this->password = $options['ntlm_password'];
        parent::__construct($wsdl, $options);
    }

}

/**
 * Camelot Soap Connection Client for NTLM Connectivity
 * 
 * @author Bendsoft
 */
class NTLMSoapClient extends SoapClient {

    /**
     * Performs a SOAP request
     * @link http://php.net/manual/en/soapclient.dorequest.php
     * 
     * @param string $request The XML Soap request
     * @param string $location Url to API
     * @param string $action The SOAP Action
     * @param int $version The SOAP Version. Unused in PHP Tools, only for PHP strict standards
     * @param int $one_way If set to 1 the method returns nothing. Unused in PHP Tools, only for PHP strict standards
     * @return SoapClient 
     */
    function __doRequest($request, $location, $action, $version, $one_way = 0) {

        $headers = array(
            'Method: POST',
            'Connection: Keep-Alive',
            'User-Agent: PHP-SOAP-CURL',
            'Content-Type: text/xml; charset=utf-8',
            'SOAPAction: "' . $action . '"',
        );

        $this->__last_request_headers = $headers;
        $ch = curl_init($location);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
        curl_setopt($ch, CURLOPT_USERPWD, $this->user . ':' . $this->password);
        $response = curl_exec($ch);

        return $response;
    }

    /**
     * Returns the SOAP headers from the last request
     * 
     * @return string 
     */
    function __getLastRequestHeaders() {
        return implode("\n", $this->__last_request_headers) . "\n";
    }

}
?>
